﻿using Exiled.API.Extensions;
using InventorySystem;
using InventorySystem.Items.Firearms.Ammo;
using InventorySystem.Items.Pickups;
using InventorySystem.Searching;
using MEC;
using RgCore.API;
using RgCore.PlayerHud;
using System.Collections.Generic;
using System.Linq;

namespace RgCore.Misc
{
    public static class InventoryLimiter
    {
        public static string GetCategoryName(ItemCategory ic)
        {
            switch (ic)
            {
                case ItemCategory.Radio:
                    return "对讲机";

                case ItemCategory.MicroHID:
                    return "MicroHID";

                case ItemCategory.Grenade:
                    return "投掷物";

                case ItemCategory.Firearm:
                    return "武器";

                case ItemCategory.SCPItem:
                    return "SCP物品";

                case ItemCategory.Medical:
                    return "医疗物品";

                case ItemCategory.Keycard:
                    return "钥匙卡";

                default:
                    return ic.ToString();
            }
        }

        public static readonly Dictionary<ItemCategory, byte> DefaultCategoryLimits = new Dictionary<ItemCategory, byte>
        {
            { ItemCategory.Firearm, 1 }, {ItemCategory.Grenade, 2}, {ItemCategory.Medical, 3 },{ItemCategory.SCPItem, 3}, {ItemCategory.Keycard, 3},
            {ItemCategory.MicroHID, 1 }, {ItemCategory.Radio, 1}
        };

        public static readonly Dictionary<ItemType, ushort> DefaultAmmoLimits = new Dictionary<ItemType, ushort>
        {
            {ItemType.Ammo12gauge,  28 },{ItemType.Ammo44cal, 30}, {ItemType.Ammo556x45, 70}, {ItemType.Ammo762x39, 60},
            {ItemType.Ammo9x19, 80 }
        };

        public static readonly Dictionary<ItemType, Dictionary<ItemCategory, byte>> ArmorItem = new Dictionary<ItemType, Dictionary<ItemCategory, byte>>
        {
            {ItemType.ArmorLight, new Dictionary<ItemCategory, byte>
            {
                {ItemCategory.Firearm, 1 }
            } },
            {ItemType.ArmorCombat, new Dictionary<ItemCategory, byte>
            {
                {ItemCategory.Firearm, 1 }, {ItemCategory.Grenade, 1}
            } },
            {ItemType.ArmorHeavy, new Dictionary<ItemCategory, byte>
            {
                {ItemCategory.Firearm, 2 }, {ItemCategory.Grenade, 2}, {ItemCategory.Medical, 1 }
            } }
        };

        public static readonly Dictionary<ItemType, Dictionary<ItemType, ushort>> ArmorAmmo = new Dictionary<ItemType, Dictionary<ItemType, ushort>>
        {
            {ItemType.ArmorLight, new Dictionary<ItemType, ushort>
            {
                {ItemType.Ammo12gauge,  0 },{ItemType.Ammo44cal, 0}, {ItemType.Ammo556x45, 40}, {ItemType.Ammo762x39, 0},
                {ItemType.Ammo9x19, 100 }
            } },
            {ItemType.ArmorCombat, new Dictionary<ItemType, ushort>
            {
                {ItemType.Ammo12gauge,  28 },{ItemType.Ammo44cal, 30}, {ItemType.Ammo556x45, 100}, {ItemType.Ammo762x39, 80},
                {ItemType.Ammo9x19, 120 }
            } },
            {ItemType.ArmorHeavy, new Dictionary<ItemType, ushort>
            {
                {ItemType.Ammo12gauge,  56 },{ItemType.Ammo44cal, 60}, {ItemType.Ammo556x45, 180}, {ItemType.Ammo762x39, 160},
                {ItemType.Ammo9x19, 200 }
            } }
        };

        public static ushort GetAmmoLimit(ItemType armor, ItemType ammo)
        {
            if (DefaultAmmoLimits.TryGetValue(ammo, out ushort amm))
            {
                ushort value = ArmorAmmo.TryGetValue(armor, out var x) ? (x.TryGetValue(ammo, out ushort r) ? r : (ushort)0) : (ushort)0;
                return (ushort)(amm + value);
            }
            return 30;
        }

        public static byte GetCategoryLimit(ItemType armor, ItemCategory item)
        {
            if (DefaultCategoryLimits.TryGetValue(item, out byte count))
            {
                byte value = ArmorItem.TryGetValue(armor, out var x) ? (x.TryGetValue(item, out byte r) ? r : (byte)0) : (byte)0;
                return (byte)(count + value);
            }
            return 8;
        }

        public static void SetEnabled()
        {
            Exiled.Events.Handlers.Player.SearchingPickup += Player_SearchingPickup;
            Exiled.Events.Handlers.Player.PickingUpItem += Player_PickingUpItem;
        }

        private static void Player_PickingUpItem(Exiled.Events.EventArgs.Player.PickingUpItemEventArgs ev)
        {
            if (ev.Pickup.Type.GetCategory() != ItemCategory.None && ev.Pickup.Type.GetCategory() != ItemCategory.Ammo)
            {
                int b = ev.Player.Inventory.UserInventory.Items.Values.Where(x => x.Category == ev.Pickup.Type.GetCategory()).Count() + 1;
                var _category = ev.Pickup.Type.GetCORRECTCategory();
                var categoryLimit = InventoryLimiter.GetCategoryLimit(ev.Player.CurrentArmor?.Type ?? ItemType.None, _category);
                if (_category == ItemCategory.None || b < categoryLimit)
                {
                    return;
                }
                if (!ev.Player.HasMsg("category_limit"))
                    ev.Player.SendFormattedMsg("category_limit", "<color=#5f7cdb>背包</color>",
                        $"<color=yellow>{InventoryLimiter.GetCategoryName(_category)}</color> 类物品已达到上限（<color=yellow>{categoryLimit}</color> 个）", 2, MsgType.Notification, ScreenLocation.CenterTop, true);
            }
            else if (ev.Pickup.Base is AmmoPickup ap)
            {
                var _ammoType = ev.Pickup.Type;
                var currentAmmo = ev.Player.Inventory.GetCurAmmo(_ammoType);
                var limit = InventoryLimiter.GetAmmoLimit(ev.Player.CurrentArmor?.Type ?? ItemType.None, _ammoType);
                if (currentAmmo + ap.SavedAmmo > limit)
                {
                    ev.IsAllowed = false;
                    Timing.CallDelayed(0.2f, delegate ()
                    {
                        ev.Pickup.InUse = false;
                        ev.Pickup.IsLocked = false;
                    });
                    ev.Player.Inventory.ServerAddAmmo(ap.NetworkInfo.ItemId, limit - currentAmmo);
                    ap.NetworkSavedAmmo = (ushort)(ap.SavedAmmo - (limit - currentAmmo));
                    PickupSyncInfo info = ev.Pickup.Info;
                    info.InUse = false;
                    ev.Pickup.Base.NetworkInfo = info;
                    if (!ev.Player.HasMsg("ammo_full"))
                        ev.Player.SendFormattedMsg("ammo_full", "<color=#5f7cdb>背包</color>",
                            $"<color=yellow>{_ammoType.ToString().Replace("Ammo", "")}</color> 弹药已抵达上限（<color=yellow>{limit}</color> 发）", 2, MsgType.Notification, ScreenLocation.CenterTop, true);
                }
            }
        }

        private static void Player_SearchingPickup(Exiled.Events.EventArgs.Player.SearchingPickupEventArgs ev)
        {
            if (ev.SearchCompletor is ItemSearchCompletor isc)
            {
                int b = ev.Player.Inventory.UserInventory.Items.Values.Where(x => x.Category == ev.Pickup.Type.GetCategory()).Count();
                var categoryLimit = GetCategoryLimit(ev.Player.CurrentArmor?.Type ?? ItemType.None, isc._category);
                if (ev.Pickup.Type.GetCategory() != ItemCategory.None)
                {
                    if (b >= categoryLimit)
                    {
                        if (!ev.Player.HasMsg("category_limit"))
                        {
                            ev.Player.SendFormattedMsg("category_limit", "<color=#5f7cdb>背包</color>",
                                $"<color=yellow>{InventoryLimiter.GetCategoryName(ev.Pickup.Type.GetCategory())}</color> 类物品已达到上限（<color=yellow>{categoryLimit}</color> 个）", 2, MsgType.Notification, ScreenLocation.CenterTop, true);
                        }
                        ev.IsAllowed = false;
                        return;
                    }
                }
                ev.IsAllowed = true;
                return;
            }
            if (ev.SearchCompletor is AmmoSearchCompletor asc)
            {
                var _ammoType = ev.Pickup.Type;
                var limit = InventoryLimiter.GetAmmoLimit(ev.Player.CurrentArmor?.Type ?? ItemType.None, _ammoType);
                if (ev.Player.Inventory.GetCurAmmo(_ammoType) >= limit)
                {
                    if (!ev.Player.HasMsg("ammo_full"))
                        ev.Player.SendFormattedMsg("ammo_full", "<color=#5f7cdb>背包</color>",
                            $"<color=yellow>{_ammoType.ToString().Replace("Ammo", "")}</color> 弹药已抵达上限（<color=yellow>{limit}</color> 发）", 2, MsgType.Notification, ScreenLocation.CenterTop, true);
                    ev.IsAllowed = false;
                    return;
                }
            }
        }
    }
}